home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 051-075 / disk_065 / pascaltoc / p2c.c < prev    next >
C/C++ Source or Header  |  1992-05-06  |  11KB  |  418 lines

  1. /*----------------------------------------------------------------------
  2.   PAS2C.C  Version 1.1
  3.   Translate Pascal keywords and operators to C.
  4.   useage:  pas2c < pascal_source  > c_source
  5.     i.e., this is a filter program which filters out the Pascal.
  6.   By James A Mullens <jcm@ornl-msr.arpa>    29-Jan-87
  7.  
  8.   Revisions:
  9.     Version 1.1  17-Feb-87  Changed several keyword translations on the
  10.     advice of James R. Van Zandt <jrv@mitre-bedford.ARPA>.  Added many
  11.     more translations.  Added a source for function strcmpi for the
  12.     unfortunates who don't have this case-insensitive string comparison
  13.     in their C library.
  14.  
  15.     Dan Kegel     15 Mar 87    Made it work on Sun workstation.  Ripped out
  16.     translations that hurt translation of a large (20,000 line) Turbo program.
  17. ----------------------------------------------------------------------*/
  18.  
  19. #include <stdio.h>    /* standard I/O */
  20. #include <ctype.h>    /* character macros */
  21. #include <string.h>    /* string functions */
  22. #include "p2c.h"
  23. #include "ktypes.h"    /* keyword type definitions */
  24.  
  25. token cTok;        /* current token from scanner */
  26. boolean WasSemi;    /* kludge to avoid duplicating semicolons */
  27.  
  28. /* Change these translations to fit your desires, but the Pascal names must 
  29.    be written in lower case and must be in alphabetical order.  If you include 
  30.    a C comment in your translation output as a HINT to the programmer, write 
  31.    it in CAPITALs, else write the comment in lower case, eh?
  32. */
  33.  
  34. wnode xlate[] = {
  35.   {T_ZIP,    "and",        "&&"    },
  36.   {T_ARRAY,    "array",    ""    },    /* see parseTypeDecl */
  37.   {T_BEGIN,    "begin",    "{"    },
  38.   {T_ZIP,    "boolean",    "boolean"},
  39.   {T_ZIP,    "byte",        "char"    },    /* Turbo */
  40.   {T_CASE,    "case",        "switch"},
  41.   {T_CONST,    "const",    "/* CONST */"},
  42.   {T_ZIP,    "div",        "/"    },
  43.   {T_ZIP,    "do",        ")"    },
  44.   {T_ZIP,    "downto",    ";/*DOWNTO*/"},
  45.   {T_ZIP,    "else",        "; else"},
  46.   {T_END,    "end",        "}"    },
  47.   {T_ZIP,    "false",    "FALSE"    },    
  48.   {T_FILE,    "file",        ""    },    /* see parseTypeDecl() */
  49.   {T_ZIP,    "for",        "for ("    },
  50.   {T_FORWARD,    "forward",    ""    },
  51.   {T_FUNC,    "function",    ""    },    /* see parseProcedure() */
  52.   {T_ZIP,    "if",        "if ("    },
  53.   {T_ZIP,    "implementation", "/* private (static) section */"},
  54.   {T_ZIP,    "input",    "stdin"    },
  55.   {T_ZIP,    "integer",    "int"    },
  56.   {T_ZIP,    "interface",    "/* exported symbol section */"},
  57.   {T_ZIP,    "ioresult",    "errno"    },    /* UCSD, Turbo */
  58.   {T_LABEL,    "label",    ""    },    /* see parseLabel() */
  59.   {T_ZIP,    "mod",        "%"    },
  60.   {T_ZIP,    "not",        "!"    },
  61.   {T_OF,    "of",        ""    },    /* see parseTypeDecl() */
  62.   {T_ZIP,    "or",        "||"    },
  63.   {T_ZIP,    "output",    "stdout"},
  64.   {T_ZIP,    "packed",    "/* PACKED */"},
  65.   {T_PROC,    "procedure",    "void"    },    /* see parseProcedure() */
  66.   {T_ZIP,    "program",    "main"    },
  67.   {T_ZIP,    "read",        "scanf"    },
  68.   {T_ZIP,    "readln",    "/*LINE*/scanf"},/* hint - read end-of-line */
  69.   {T_ZIP,    "real",        "double"},    /* or "float" */
  70.   {T_RECORD,    "record",    ""    },    /* see parseTypeDecl() */
  71.   {T_ZIP,    "repeat",    "do {"    },
  72.   {T_STRINGTYPE,"string",    ""    },    /* UCSD, Turbo string type */
  73.   {T_ZIP,    "text",        "FILE *"},    /* UCSD, Turbo file type */
  74.   {T_ZIP,    "then",        ")"    },
  75.   {T_ZIP,    "to",        ";"    },
  76.   {T_ZIP,    "true",        "TRUE"    },    
  77.   {T_TYPE,    "type",        ""    },    /* see parseType() */
  78.   {T_ZIP,    "until",    "} until ("},
  79.   {T_ZIP,    "uses",        "/* USES */\n#include"},
  80.   {T_VAR,    "var",        "/* VAR */"},    /* see parseProc, parseVar() */
  81.   {T_ZIP,    "while",    "while ("},
  82.   {T_ZIP,    "with",        "/* WITH */"},    /*hint-set pointer to struct*/
  83.   {T_ZIP,    "write",    "printf"},
  84.   {T_ZIP,    "writeln",    "/*LINE*/printf"},/* hint - write newline */
  85.   {T_ZIP,    "",        ""    }    /* marks end of xlate table */
  86. };
  87.  
  88. wnode theend = {T_ZIP,    "", ""};
  89.  
  90. wnode *hash[26];        /* quick index into the translation array */
  91.  
  92. /* Fill in the quick index ("hash") array 
  93. */
  94. void init_hash()
  95. {
  96.     int ch, cmp;
  97.     wnode *nptr = xlate;
  98.  
  99.     for (ch='a'; ch<='z'; ch++) {
  100.     while (nptr->pname[0] && (cmp = ch - *nptr->pname) > 0) 
  101.         nptr++;
  102.     hash[ch-'a'] = (cmp==0) ? nptr : &theend;
  103.     }
  104. }
  105.  
  106.  
  107. /* compare two strings without regard to case,
  108.    the equivalent of this function may already be in your C library 
  109.    Used to fail on Suns because it used tolower on lowercase chars...
  110.    Assumes second argument already lowercase.
  111. */
  112. int strcmpi(s1,s2)
  113.     register char *s1, *s2;
  114.     register char c1;
  115.  
  116.     while ((c1= *s1++) && *s2) {    /* get char, advance ptr */
  117.     if (isupper(c1)) c1 = tolower(c1);
  118.     if (c1 != *s2) break;
  119.     s2++;
  120.     }
  121.     return(c1 - *s2);
  122. }
  123.  
  124.  
  125. /* Pass an identifier through the translation table; return its
  126.    keyword type.  Translated keyword left in same buffer.
  127. */
  128. int
  129. translate(word)
  130.     register char *word;
  131.     register wnode *xptr;
  132.     int nomatch;
  133.     int c;
  134.  
  135.     c = *word;
  136.     if (isalpha(c)) {
  137.     if (isupper(c)) c=tolower(c);
  138.     xptr = hash[c - 'a'];
  139.     while ( xptr->pname[0] && (nomatch = strcmpi(word,xptr->pname)) > 0 ) 
  140.         xptr++;
  141.     if (!nomatch) {
  142.         word[0]=0;
  143.         if (!WasSemi && xptr->ktype == T_END)
  144.         strcpy(word, ";");
  145.         strcat(word, xptr->cname);
  146.         return(xptr->ktype);
  147.     }
  148.     }
  149.     return(T_ZIP);
  150. }
  151.  
  152. #define Q_NOQUOTE  1
  153. #define Q_ONEQUOTE 2
  154. #define Q_DONE     3
  155. #define Q_ERR      4
  156.  
  157. #define Q_C_ESCAPES  FALSE   /* Set true if your Pascal knows backslashes */
  158.  
  159. /*---- parseQuotedString -------------------------------------------------
  160. Accepts Pascal quoted string from stdin, converts to C quoted string, and 
  161. places in buf.
  162. Examples:
  163.   'hi' -> "hi"    'hi''' -> "hi'"  'hi''''' -> "hi''"
  164.   ''   -> ""      ''''   -> "'"    ''''''   -> "''"
  165.   ''hi' -> ERROR  '''hi' -> "'hi"  '''''hi' -> "''hi"
  166.   'I''m'  -> "I'm"
  167. Double quotes and backslashes are preceded with backslashes, except that
  168. if Q_C_ESCAPES is TRUE, backslashes are left naked.
  169. --------------------------------------------------------------------------*/
  170. void
  171. parseQuotedString(buf)
  172. char *buf;
  173. {
  174.     register char c;
  175.     register char *letter=buf;
  176.     int qstate;
  177.  
  178.     *letter++ = '"';
  179.     qstate = Q_NOQUOTE;
  180.     while (qstate < Q_DONE) {
  181.     switch (c=getchar()) {
  182.     case '\'':
  183.         switch (qstate) {
  184.         case Q_NOQUOTE:  
  185.         qstate = Q_ONEQUOTE; break;
  186.         case Q_ONEQUOTE: 
  187.         *letter++ = c; qstate = Q_NOQUOTE; break;
  188.         }
  189.         break;
  190.     case EOF:
  191.     case '\n':
  192.         qstate= (qstate==Q_ONEQUOTE) ? Q_DONE : Q_ERR;
  193.         ungetc(c,stdin);
  194.         break;
  195.     default:
  196.         switch (qstate) {
  197.         case Q_ONEQUOTE: 
  198.         ungetc(c,stdin); qstate = Q_DONE; break;
  199.         case Q_NOQUOTE:
  200.         if (c=='\\' && !Q_C_ESCAPES) *letter++ = c;
  201.         if (c=='"') *letter++ = '\\';
  202.         *letter++ = c; 
  203.         break; 
  204.         }
  205.     }
  206.     }
  207.     *letter++ = '"';
  208.     *letter++ = '\0';
  209.     if (qstate == Q_ERR) {
  210.     fprintf(stderr,"Newline in string constant: %s\n",buf);
  211.     fprintf(stdout," %c*** \\n IN STRING ***%c ",
  212.         '/', buf, '/');
  213.     }
  214. }
  215.  
  216. void
  217. getTok()
  218. {
  219.     register char *letter = cTok.str;
  220.     register char *sEnd = letter + MAXTOKLEN-3;
  221.     register int c;
  222.  
  223.     c = getchar();
  224.     if (isalnum(c)) {
  225.     while (c != EOF && isalnum(c)) {
  226.         *letter++ = c;
  227.         c = getchar();
  228.     }
  229.     ungetc(c,stdin);
  230.     *letter++ = 0;
  231.     cTok.kind = translate(cTok.str);
  232.     } else {
  233.     switch(c) {
  234.     case '\n':    /* newline */
  235.     case 0x20:    /* space */
  236.     case 0x9:    /* tab */
  237.         do        /* Gather a string of blank space into one token */
  238.         *letter++ = c;
  239.         while ((c=getchar()) != EOF && isspace(c));
  240.         ungetc(c, stdin);
  241.         *letter++ = '\0';
  242.         cTok.kind = T_SPACE;
  243.         break;
  244.     case '\'':                 /* Quoted String */
  245.         parseQuotedString(cTok.str);
  246.         cTok.kind = T_STRING;
  247.         break;
  248.     case '{' :                 /* Curly Comment */
  249.         *letter++='/'; 
  250.         *letter++='*';
  251.         while ((c=getchar()) != EOF && c!='}' && letter!=sEnd)
  252.         *letter++ = c;
  253.         if (letter == sEnd) {
  254.         printf("/***ERROR: Comment too long (sorry) ***/");
  255.         while ((c=getchar()) != EOF && c!='}')
  256.             ;
  257.         }
  258.         strcpy(letter, "*/");
  259.         cTok.kind = T_COMMENT;
  260.         break;
  261.     case '(' : 
  262.         if ((c=getchar())!='*') {        /* Parenthesis */
  263.         ungetc(c,stdin);
  264.         strcpy(letter, "(");
  265.         cTok.kind = T_LPAREN;
  266.         } else {
  267.         register int lastc = '\0';    /* (* Comment *) */
  268.         *letter++='/'; 
  269.         *letter++='*';
  270.         while ((c=getchar())!=EOF && !(c==')' && lastc == '*') && 
  271.             letter != sEnd) {
  272.             lastc = c;
  273.             *letter++ = c;
  274.         }
  275.         if (letter == sEnd) {
  276.             printf("/***ERROR: Comment too long (sorry) ***/");
  277.             while ((c=getchar())!=EOF && !(c==')' && lastc == '*'))
  278.             lastc = c;
  279.         }
  280.         strcpy(letter, "/");        /* * already there! */
  281.         cTok.kind = T_COMMENT;
  282.         }
  283.         break;
  284.     case ')' :
  285.         strcpy(letter, ")");
  286.         cTok.kind = T_RPAREN;
  287.         break;
  288.     case ':' : 
  289.         if ((c=getchar())=='=') {        /* Assignment */
  290.         strcpy(letter, "=");
  291.         cTok.kind = T_ASSIGN;
  292.         } else {                /* Colon */
  293.         ungetc(c,stdin);
  294.         strcpy(letter, ":");
  295.         cTok.kind = T_COLON;
  296.         }
  297.         break;
  298.     case '=':
  299.         strcpy(letter, "==");        /* Might be equality test...*/
  300.         cTok.kind = T_EQUALS;        /* depends on parse state */
  301.         break;
  302.     case '<' : 
  303.         switch (c=getchar()) {
  304.         case '>':  
  305.         strcpy(letter, "!=");
  306.         break;
  307.         case '=':  
  308.         strcpy(letter, "<=");
  309.         break;
  310.         default :  
  311.         ungetc(c,stdin);
  312.         strcpy(letter,"<");
  313.         }
  314.         cTok.kind = T_COMPARE;
  315.         break;
  316.     case '>' : 
  317.         if ((c=getchar()) == '=')
  318.         strcpy(letter, ">=");
  319.         else {
  320.         ungetc(c,stdin);
  321.         strcpy(letter, ">");
  322.         }
  323.         cTok.kind = T_COMPARE;
  324.         break;
  325.     case '^' :
  326.         if ((c=getchar()) == '.') {    /* perhaps we should skip blanks? */
  327.         strcpy(letter, "->");
  328.         cTok.kind = T_STRUCTMEMBER;
  329.         } else {
  330.         ungetc(c,stdin);
  331.         strcpy(letter, "[0]");    /* '*' would have to go in front */
  332.         cTok.kind = T_DEREF;
  333.         }
  334.         break;
  335.     case '$' :            /* Turbo Pascal extension */ 
  336.         strcpy(letter, "0x");
  337.         cTok.kind = T_ZIP;
  338.         break;
  339.     case ';' :             /* Semicolon- translation depends on */
  340.         strcpy(letter, ";");    /* parse state... */
  341.         cTok.kind = T_SEMI;
  342.         break;
  343.     case '.':
  344.         if ((c=getchar()) == '.') {
  345.         cTok.kind = T_RANGE;
  346.         letter[0]=0;
  347.         } else {
  348.         ungetc(c,stdin);
  349.         strcpy(letter, ".");
  350.         cTok.kind = T_ZIP;
  351.         }
  352.         break;
  353.     case '[':
  354.         *letter++ = c; *letter = '\0';
  355.         cTok.kind = T_LBRACKET;
  356.         break;
  357.     case ']':
  358.         *letter++ = c; *letter = '\0';
  359.         cTok.kind = T_RBRACKET;
  360.         break;
  361.     case ',':
  362.         *letter++ = c; *letter = '\0';
  363.         cTok.kind = T_COMMA;
  364.         break;
  365.     case EOF:            /* end of file */
  366.         cTok.kind = T_EOF;
  367.         break;
  368.     default: 
  369.         *letter++ = c;        /* Pass unknown chars thru as tokens */
  370.         *letter = '\0';
  371.         cTok.kind = T_ZIP;
  372.     }
  373.     }
  374. }
  375.  
  376. main(argc, argv)
  377. int argc;
  378. char **argv;
  379. {
  380.     int debug;
  381.     
  382.     debug = (argc > 1);
  383.     init_hash();
  384.     WasSemi = FALSE;
  385.  
  386.     getTok(); 
  387.     do {
  388.     switch(cTok.kind) {
  389.     case T_VAR:
  390.         parseVar();
  391.         break;
  392.     case T_PROC:
  393.     case T_FUNC:
  394.         parseProcedure();
  395.         break;
  396.     case T_LABEL:
  397.         parseLabel();
  398.         break;
  399.     case T_TYPE:
  400.         parseType();
  401.         break;
  402.     default:
  403.         if (debug)
  404.         printf("'%s' %d\n", cTok.str, cTok.kind);
  405.         else {    /* fancy stuff to avoid duplicating semicolons */
  406.         if (cTok.kind != T_SEMI || !WasSemi)
  407.             fputs(cTok.str, stdout);
  408.         if (cTok.kind != T_SPACE && cTok.kind != T_COMMENT)
  409.             WasSemi = (cTok.kind == T_SEMI);
  410.         }
  411.         getTok();
  412.     }
  413.     } while (cTok.kind != T_EOF);
  414. }
  415.  
  416.